﻿// -----------------------------------------------------------------------
//  <copyright file="UserFilterValueProvider.cs" company="LiuliuSoft">
//      Copyright (c) 2025 66SOFT. All rights reserved.
//  </copyright>
//  <site>https://ifs.66soft.net</site>
//  <last-editor>郭明锋</last-editor>
//  <last-date>2025-10-23 23:10</last-date>
// -----------------------------------------------------------------------

using System.Security.Claims;

namespace DaprPlus.Filters;

public class UserFilterValueProvider(IServiceProvider provider) : IFilterValueProvider
{
    /// <summary>
    /// 获取支持的标记前缀
    /// </summary>
    public string Prefix => "@User";

    /// <summary>
    /// 检查是否支持指定的标记
    /// </summary>
    /// <param name="token">标记</param>
    /// <returns></returns>
    public bool CanHandle(string token)
    {
        return token.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase);
    }

    /// <summary>
    /// 获取动态值
    /// </summary>
    /// <param name="token">标记</param>
    /// <param name="targetType">目标类型</param>
    /// <returns>动态值</returns>
    public object? GetValue(string token, Type targetType)
    {
        var principal = provider.GetCurrentUser();
        if (principal?.Identity?.IsAuthenticated != true)
        {
            throw new InvalidOperationException("用户未登录");
        }

        if (principal.Identity is not ClaimsIdentity identity)
        {
            return null;
        }

        return token.ToLowerInvariant() switch
        {
            "@userid" => GetClaimValue(identity, ClaimTypes.NameIdentifier, targetType)?? GetClaimValue(identity, "sub", targetType),
            "@username" => GetClaimValue(identity, ClaimTypes.Name, targetType) ?? GetClaimValue(identity, "name", targetType),
            "@useremail" => GetClaimValue(identity, ClaimTypes.Email, targetType) ?? GetClaimValue(identity, "email", targetType),
            "@userrole" => GetClaimValue(identity, ClaimTypes.Role, targetType),
            _ => null
        };
    }


    private object? GetClaimValue(ClaimsIdentity identity, string claimType, Type targetType)
    {
        var value = identity.FindFirst(claimType)?.Value;
        return value?.CastTo(targetType);
    }
}